package ohc.login

import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents
import net.fabricmc.fabric.api.event.player.AttackBlockCallback
import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents
import net.fabricmc.fabric.api.event.player.UseBlockCallback
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents
import net.minecraft.server.MinecraftServer
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.text.Text
import net.minecraft.util.ActionResult
import net.minecraft.util.Formatting

/**
 * 事件处理器注册类
 */
object EventHandlers {
    
    private var tickCounter = 0
    private const val TICK_INTERVAL = 20  // 每秒检查一次（20 tick = 1 秒）
    
    /**
     * 注册所有事件处理器
     */
    fun register() {
        // 注册命令
        CommandRegistrationCallback.EVENT.register { dispatcher, _, _ ->
            Commands.register(dispatcher)
        }
        
        // 服务器启动事件，初始化自动存档
        ServerLifecycleEvents.SERVER_STARTED.register { server ->
            BackupManager.init(server)
        }
        
        // 玩家加入事件
        ServerPlayConnectionEvents.JOIN.register { handler, _, server ->
            val player = handler.player
            
            // 检查是否被封禁
            val banHours = LoginManager.getBanRemainingHours(player.uuid)
            if (banHours != null) {
                player.networkHandler.disconnect(
                    Text.literal("§c您因密码错误次数过多被封禁，剩余时间: ${String.format("%.1f", banHours)} 小时")
                )
                return@register
            }
            
            LoginManager.onPlayerJoin(player)
            
            // 管理员更新检测
            if (player.hasPermissionLevel(2)) {
                checkAndNotifyUpdate(player, server)
            }
        }
        
        // 玩家离开事件
        ServerPlayConnectionEvents.DISCONNECT.register { handler, _ ->
            val player = handler.player
            LoginManager.onPlayerLeave(player)
        }
        
        // 服务器 tick 事件，用于检查超时
        ServerTickEvents.END_SERVER_TICK.register { server ->
            onServerTick(server)
        }
        
        // 阻止未登录玩家破坏方块
        PlayerBlockBreakEvents.BEFORE.register { world, player, pos, state, blockEntity ->
            if (player is ServerPlayerEntity && !LoginManager.isLoggedIn(player.uuid)) {
                sendNotLoggedInMessage(player)
                false  // 返回 false 阻止破坏
            } else {
                true
            }
        }
        
        // 阻止未登录玩家使用方块（放置、交互）
        UseBlockCallback.EVENT.register { player, world, hand, hitResult ->
            if (player is ServerPlayerEntity && !LoginManager.isLoggedIn(player.uuid)) {
                sendNotLoggedInMessage(player)
                ActionResult.FAIL  // 返回 FAIL 阻止操作
            } else {
                ActionResult.PASS
            }
        }
        
        // 阻止未登录玩家攻击方块（开始挖掘）
        AttackBlockCallback.EVENT.register { player, world, hand, pos, direction ->
            if (player is ServerPlayerEntity && !LoginManager.isLoggedIn(player.uuid)) {
                ActionResult.FAIL
            } else {
                ActionResult.PASS
            }
        }
        
        Ohc_login.logger.info("已注册事件处理器")
    }
    
    /**
     * 服务器 tick 处理
     */
    private fun onServerTick(server: MinecraftServer) {
        tickCounter++
        
        // 每 tick 更新追踪显示（ActionBar 需要频繁刷新）
        Commands.updateTracking(server)
        
        if (tickCounter < TICK_INTERVAL) return
        tickCounter = 0
        
        // 检查所有待登录玩家
        val pendingPlayers = LoginManager.getPendingPlayers()
        for (uuid in pendingPlayers) {
            val player = server.playerManager.getPlayer(uuid) ?: continue
            
            // 检查超时
            if (LoginManager.isTimeout(uuid)) {
                if (Config.kickOnTimeout) {
                    player.networkHandler.disconnect(Text.literal("§c登录超时，请重新连接。"))
                    continue
                }
            }
            
            // 每 10 秒提醒一次
            val remainingTime = LoginManager.getRemainingTime(uuid)
            if (remainingTime > 0 && remainingTime % 10 == 0) {
                player.sendMessage(
                    Text.literal("§e请在 ${remainingTime} 秒内登录").formatted(Formatting.YELLOW),
                    true  // 显示在动作栏
                )
            }
        }
    }
    
    /**
     * 发送未登录提示消息
     */
    private fun sendNotLoggedInMessage(player: ServerPlayerEntity) {
        val needBind = LoginManager.needsBind(player.uuid)
        if (needBind) {
            player.sendMessage(
                Text.literal("§c请先使用 /bind <账号> <密码> 绑定账号！").formatted(Formatting.RED),
                true
            )
        } else {
            player.sendMessage(
                Text.literal("§c请先使用 /l <密码> 登录！").formatted(Formatting.RED),
                true
            )
        }
    }
    
    /**
     * 检测更新并通知管理员
     */
    private fun checkAndNotifyUpdate(player: ServerPlayerEntity, server: MinecraftServer) {
        UpdateChecker.checkUpdateAsync().thenAccept { info ->
            if (!info.hasUpdate) return@thenAccept
            val url = info.downloadUrl ?: return@thenAccept
            
            // 回到主线程发送消息
            server.execute {
                player.sendMessage(Text.literal(""), false)
                player.sendMessage(
                    Text.literal("§6[OHC Login] §e发现新版本: §a${info.latestVersion} §7(当前: ${info.currentVersion})"),
                    false
                )
                player.sendMessage(
                    Text.literal("§6[OHC Login] §e下载地址: §b§n$url"),
                    false
                )
                player.sendMessage(Text.literal(""), false)
            }
        }
    }
}
